<template>
  <div :id="tableId" class="ez-table-component height-100">
    <div
      class="table-content"
      :class="{'table-without-fit': !fitTable}"
      :style="{height: rows.length > 0 && !hidePagination ? `calc(100% - 50px)` : '100%'}">
      <div :id="`${tableId}-topArea`">
        <slot name="header"></slot>
        <EZTableFilter
          v-if="!hideFilter"
          :table-id="tableId"
          :table-hdl="tableHdl"
          class="pad-btm-10"
          @filterChange="filterChange">
          <div slot="customOpts">
            <slot name="customOpts"></slot>
          </div>
        </EZTableFilter>
      </div>
      <el-table
        :ref="`${tableId}-table`"
        :data="rows"
        :border="true"
        :stripe="true"
        :height="`calc(100% - ${filterHeight}px)`"
        :row-key="uniqueKey"
        @selection-change="selectionChange"
        @sort-change="sortChanged">
        <el-table-column
          v-if="selectable"
          :selectable="rowSelectableHdl"
          :reserve-selection="true"
          type="selection"
          width="55"></el-table-column>
        <el-table-column v-if="expand" type="expand"></el-table-column>
        <el-table-column
          v-for="(c, idx) in columns"
          v-if="!c['hide']"
          :fixed="idx === 0 && !c['notFixed'] ? 'left': c['operation'] ? 'right': false"
          :reserve-selection="true"
          :sortable="c.sort ? 'custom' : false"
          :prop="c.prop"
          :label="c.label"
          :width="c['operation'] ? getWidthText(c.width) : ''"
          :min-width="getWidthText(c.width)"
          :key="c.label">
          <template slot-scope="scope">
            <EZColumn
              :tableId="tableId"
              :horizontal="c.horizontal"
              :hover="c.hover"
              :children="c.children"
              :parent="c"
              :data="rows[scope.$index]"></EZColumn>
          </template>
        </el-table-column>
        <template v-if="rows.length === 0" slot="append">
          <slot v-if="$slots.empty" name="empty"></slot>
          <EmptyContent v-else></EmptyContent>
        </template>
      </el-table>
    </div>
    <el-pagination
      v-if="rows.length > 0 && !hidePagination"
      :page-sizes="pageSizes"
      :total="total"
      :current-page.sync="pageNo"
      :page-size.sync="pageSize"
      :pager-count="5"
      :style="paginationStyle"
      class="table-pagination width-100"
      background
      :layout="paginationLayout"
      @current-change="pageChanged"
      @size-change="sizeChanged">
    </el-pagination>
    <CustomTooltip
      :id="`${tableId}-tableColumnTooltip`"
      :ref="`${tableId}-tableColumnTooltip`"
      :open-delay="800"
      :hide-arrow="true"
      :offset="[0, 10]"
      :rely-class="`${tableId}-column-tooltip-content`"></CustomTooltip>
  </div>
</template>

<script>
  import EZTableFilter from './tableFilter/EZTableFilter';
  import EZColumn from './EZColumn.vue';
  import CustomTooltip from '../CustomTooltip.vue';
  import EmptyContent from '../EmptyContent';
  import {mapState} from 'vuex';
  import {commonConfig} from "@/config/common";

  const elementResizeDetectorMaker = require('element-resize-detector');

  export default {
    name: 'EZTable',
    components: {EZTableFilter, EZColumn, CustomTooltip, EmptyContent},
    props: {
      // table 的唯一标志，用于 store 的存取
      tableId: {
        type: String,
        default: ''
      },
      tableHdl: { // 表格处理
        type: Object,
        default: () => {
          return {};
        }
      },
      fitTable: {
        type: Boolean,
        default: true
      },
      // row 数据的唯一字段标志
      uniqueKey: {
        type: String,
        default: '_id'
      },
      rows: {
        type: Array,
        default: () => {
          return [];
        }
      },
      selectable: {
        type: Boolean,
        default: false
      },
      rowSelectableHdl: {
        type: Function,
        default: () => {
          return () => {
            return true
          };
        }
      },
      expand: {
        type: Boolean,
        default: false
      },
      customEmpty: {
        type: Boolean,
        default: false
      },
	    paginationLayout: {
		    type: String,
		    default: 'total, sizes, prev, pager, next'
	    },
      hideFilter: { // 是否隐藏筛选条件
        type: Boolean,
        default: false
      },
      hidePagination: {
        type: Boolean,
        default: false
      }
    },
    data() {
      return {
        filterHeight: 0,
        columns: [],
        pageNo: 1,
        pageSize: commonConfig.defaultPageSize,
        pageSizes: [10, 15, 30, 50, 100],
        total: 0,
        sortResult: []
      };
    },
    computed: {
      ...mapState({
        clientHeight: state => state.client.clientHeight,
        breadcrumbHeight: state => state.client.breadcrumbHeight,
        routeParamState: state => state.routeParam.routeParamState,
      }),
      paginationStyle() {
        return this.fitTable ? {position: 'absolute', bottom: 0} : {marginTop: '20px'};
      }
    },
    watch: {
      tableHdl: {
        handler(tableHdl) {
          if (_.isEmpty(tableHdl)) return;
          this.columns = tableHdl.columnConfig;
          this.pageNo = tableHdl.pageNo;
          this.pageSize = tableHdl.pageSize;
          this.total = tableHdl.total;
          this.sortResult = tableHdl.sortResult;
        },
        immediate: true,
        deep: true // tableHdl 为 TableHdl Class，需配置深度监听
      },
      rows() {
        this.$nextTick(() => {
          const tooltip = this.$refs[`${this.tableId}-tableColumnTooltip`];
          tooltip && tooltip.init();
        });
      }
    },
    mounted() {
      this.calculateHeight();
    },
    deactivated() {
      const tooltip = this.$refs['inspectionTooltip'];
      tooltip && tooltip.destroy();
    },
    destroyed() {
      const tooltip = this.$refs['inspectionTooltip'];
      tooltip && tooltip.destroy();
    },
    methods: {
      clearSelection(){
        this.$refs[`${this.tableId}-table`].clearSelection()
      },
      calculateHeight() {
        const filter = document.getElementById(`${this.tableId}-topArea`);
        if (!filter) return;
        const erd = elementResizeDetectorMaker();
        erd.listenTo(filter, (element) => {
          this.filterHeight = element.offsetHeight;
        });
      },
      getWidthText(width = 0) {
        return width ? `${width}px` : '';
      },
      pageChanged(page) {
        this.tableHdl.updateTableParam({pageNo: page});
        this.$emit('pageChanged');
      },
      sizeChanged(size) {
        // 分页时当前页码默认为第一页
        this.tableHdl.updateTableParam({pageSize: size, pageNo: ''});
        this.$emit('sizeChanged');
      },
      sortChanged({prop, order}) { // 表格的排序条件发生变化
        const destOrder = order === 'descending' ? 'desc' : 'asc'; // 升序，倒序
        // 先移除已有 sort，在将新的 sort 插入到首位，后台根据数据元素的顺序来决定排序优先级
        const existIdx = _.map(this.sortResult, 'key').indexOf(prop);
        if (~existIdx) {
          this.sortResult.splice(existIdx, 1);
        }
        this.sortResult.unshift({key: prop, type: destOrder});
        this.tableHdl.updateTableParam({sort: this.sortResult, pageNo: 1});
        this.$emit('sortChanged');
      },
      filterChange() { // 表格的筛选条件发生变化
        this.$emit('filterChange');
      },
      selectionChange(selection) {
        this.$emit('selectionChange', selection);
      },
      // 重新布局，当 table 或其父元素由隐藏切换为显示时，需要重新布局，
      // 否则会导致 table 高度显示会有问题 Henry 2022-03-10 10:23:55
      relayout() {
        this.$nextTick(() => {
          const table = this.$refs[`${this.tableId}-table`];
          if (!table) return;
          table.doLayout();
        })
      }
    }
  };
</script>

<style scoped>
</style>
